﻿using System;
using System.Collections.Generic;
using System.Data;
using System.Text;
using Dzzzr.DataLayer;
using Dzzzr.Utils;

namespace Dzzzr
{
	public class GameEntityController
	{
		//Куда кидается объект
		public enum DropPosition
		{
			Into, //Внутрь узла
			Before, //До узла
			After//После узла
		}
		private const int MaxNestLevel = 2;

		/// <summary>
		/// Возвращает список НЕназначенных на игру сущностей
		/// </summary>
		/// <param name="gameID">Идентификатор игры</param>
		/// <returns></returns>
		public static List<Entity> GetUnusedGameEntities(int gameID)
		{
			IDataReader rd = GameEntityProvider.GetUnusedGameEntities(gameID);
			return CBO.FillCollection<Entity, List<Entity>>(typeof(Entity), rd); ;
		}

		/// <summary>
		/// Возвращает список назначенных на игру сущностей
		/// </summary>
		/// <param name="gameID">Идентификатор игры</param>
		/// <returns></returns>
		public static GameEntityInfoList GetUsedGameEntities(int gameID)
		{
			IDataReader rd = GameEntityProvider.GetUsedGameEntities(gameID);
			return CBO.FillCollection<GameEntityInfo, GameEntityInfoList>(typeof(GameEntityInfo), rd);
		}

		private static void AssignEntity(GameEntityInfo entity)
		{
		}

		/// <summary>
		/// Назначает сущность на игру(в заданной позиции), в не зависимости от того, была ли она уже назначена или нет
		/// </summary>
		/// <param name="gameID">Идентификатор игры</param>
		/// <param name="sourceID">ID добавляемой сущности</param>
		/// <param name="destID">ID сущности рядом с которой добавляем сущность</param>
		/// <param name="dropPosition">Позиция добавляемой сущности относительно сущности-назначения</param>
		public static void SetEntity(int gameID, int sourceID, int destID, DropPosition dropPosition)
		{
			GameEntityInfoList list = GetUsedGameEntities(gameID);//Получаем список назначенных сущностей
			GameEntityInfo dest = list.FindByEntityID(destID);//накодим сущность-приемник
			GameEntityInfo source = list.FindByEntityID(sourceID);//находим сущность источник
			if (source == null)//Если сущность еще не была назначена
			{
				source = new GameEntityInfo();//создаем сущность
				source.GameID = gameID;
				source.EntityID = sourceID;
			}
			if (dest == null)//Если еще никто не назначен
			{
				dest = new GameEntityInfo();//создаем фейковую сущность
				dest.GameID = gameID;
				dest.EntityID = null;
			}

			//Получаем список узлов того уровня, к которому добавляем сущность
			GameEntityInfoList destLevelList = list.FindLevelByParentEntityID(dropPosition == DropPosition.Into ? dest.EntityID : dest.ParentID);
			destLevelList.Normalize();//Нормализуем список узлов (на всякий случай)
			switch (dropPosition)//Задаем номер узла в своем уровне в зависимости от позиции вставки
			{
				case DropPosition.Into:
					source.OrderNumber = 0;
					source.ParentID = dest.EntityID;
					break;
				case DropPosition.After:
					source.OrderNumber = dest.OrderNumber + 1;
					source.ParentID = dest.ParentID;
					break;
				case DropPosition.Before:
					source.OrderNumber = dest.OrderNumber;
					source.ParentID = dest.ParentID;
					break;
				default:
					throw new ArgumentOutOfRangeException("dropPosition");
			}

			//Сдвигаем элементы c номером узла больше или равно чем у вставляемого
			foreach (GameEntityInfo entityInfo in destLevelList)
			{
				if (entityInfo != source && entityInfo.OrderNumber >= source.OrderNumber)
					entityInfo.OrderNumber++;
			}

			if(list.IndexOf(source) == -1)
				list.Add(source);
			
			destLevelList.Normalize();
			//Сортируем в порядке убывания номеров(на всякий случай :) )
			//destLevelList.Sort(delegate(GameEntityInfo x, GameEntityInfo y) { return x.OrderNumber == y.OrderNumber ? 0 : x.OrderNumber > y.OrderNumber ? -1 : 1; });
      //Обновляем все сущности уровня приемника
			foreach (GameEntityInfo entityInfo in destLevelList)
			{
				GameEntityProvider.AssignEntity(entityInfo);
			}

			//Получаем список узлов с уровня узла-источника
			GameEntityInfoList sourceLevelList = list.FindLevelByParentEntityID(source.ParentID);
			sourceLevelList.Normalize();
			//Сортируем в порядке убывания номеров(на всякий случай :) )
			//sourceLevelList.Sort(delegate(GameEntityInfo x, GameEntityInfo y) { return x.OrderNumber == y.OrderNumber ? 0 : x.OrderNumber > y.OrderNumber ? -1 : 1; });
			//Обновляем все сущности уровня источника
			foreach (GameEntityInfo entityInfo in sourceLevelList)
			{
				GameEntityProvider.AssignEntity(entityInfo);
			}
		}

		public static void DeleteAssignment(GameEntityInfo entity)
		{
			GameEntityProvider.DeleteAssignment(entity);
		}

		private static bool ValidateDeletion(GameEntityInfo entity)
		{
			if (entity.ParentID == -1)
			{
				return false;
			}
			else
			{
				return true;
			}
		}

		private static bool ValidateAssignment(GameEntityInfo entity)
		{
			if (entity.ParentID == -1)
			{
				return true;
			}
			else
			{
				return false;
			}
		}

	}
}
